SELinux 教學與設定

以往我們架一個 service,只要注意使用者與資料夾的權限有弄對,防火牆的 port 有開通就好,例如 samba 或 ftp。防火牆一打開,資料夾給予寫入或讀取的權限,就可以讓人連進來上傳下載檔案。

不過現在的 Linux 除了基本的檔案權限與防火牆以外,又多了 SELinux 這個額外的防護機制。以最近除錯的經驗來看,當 service 怎樣都找不出哪裡有問題時,很有可能都是與 SELinux 有關。

相較於常用的檔案目錄權限觀念,SELinux 確實複雜了不少,因此很多人都選擇關掉它,不過個人覺得既然 SELinux 這麼難搞,那就表示它真的可以增加不少安全性,所以可以的話還是先別關閉它吧!

SELinux 基本概念

SELinux 的全名為 Security Enhanced Linux,顧名思義就是為 Linux 提供了更進一步的安全防護。

在 Linux 中,一個檔案或資料夾能不能查看或是刪除,我們常用 user、group 與讀寫、執行的權限來作最基本的安全管控,而 SELinux 我們可以把它當作一套附加的安全機制,有別於傳統 user group 的管理,它是針對系統中的物件,例如:資料夾、檔案、process、port,加上一層專有的安全條文來規範什麼可以做什麼不能做

舉例來說,常見的網頁 server Apache 預設都可讀取 /var/www/html 裡的內容,但如果今天我程式寫錯了,讓我的 php 網頁去讀 /tmp 裡的東西,由於 /tmp 在系統裡預設的權限是 777,表示 apache 是可以隨意讀寫 /tmp 的,如果 /tmp 裡有什麼特別的資料,等於全世界連上我的網站的人都有機會看到我的敏感資料了,SELinux 就是在避免這種情況的發生。

基本上 SELinux 的安全機制就是在管理 process 是否可以讀寫檔案、資料夾或是使用 port。它為每個檔案、資料夾、port 加上了專屬的標籤,稱為 SELinux context(SELinux 安全脈絡),透過這個標籤,可以區分每個程式所能讀寫的檔案、資料夾,或是允許使用的 port 是什麼。

例如我們用 Apache 架網站的內容一般都是放在 /var/www/ 裡面,這個資料夾預設的標籤通常是允許 Apache 來讀取,但如果今天我不想把網頁資料放 /var/www,想放在我的 home 目錄,一般而言 home 目錄預設的標籤是不允許讓 httpd 來存取的,所以瀏覽網頁時一定會失敗,即使 Home 目錄的擁有者是 Apache,權限還設成 777。因此這時要將 home 目錄的 context type 改成與 /var/www 一樣,Apache 才能正常的讀取網頁的資料。

關於 SELinux 的 Security Context

前面提到 SELinux context 為每個檔案、資料夾與 port、process 都加上了屬於它的預設標籤,如果這個標籤的 type 不對,就會有無法讀寫的問題。security context 的標籤命名通常是以一串英文最後結尾加上 _t,這邊我就用 apache 為例來試範如何查詢系統物件(檔案、資料夾、process、port)的標籤。

查詢檔案與資料夾的 Security Context

在 ls 的指令中加上參數 Z 即可檢視

ls -lZ /var/www/html
# 執行結果
    
drwxr-xr-x. 4 root   root  system_u:object_r:httpd_sys_content_t:s0          71 Mar 29 03:16 .
drwxr-xr-x. 4 root   root  system_u:object_r:httpd_sys_content_t:s0          33 Mar 28 15:23 ..
-rw-r--r--. 1 apache apacheunconfined_u:object_r:httpd_sys_content_t:s0     287 Mar 28 16:50 index.html
drwxr-xr-x. 2 apache apacheunconfined_u:object_r:httpd_sys_content_t:s0       6 Mar 28 17:11 upload
-rw-r--r--. 1 apache apache unconfined_u:object_r:httpd_sys_content_t:s0   1064 Mar 28 17:10 upload.php

httpd_sys_content_t 為 /var/www/html 這個資料夾的標籤,同時也是底下三個檔案的標籤。

查詢 Process 的 Security Context

在 ps 指令中加上參數 -Z 可以看到 process 的 context type

ps -eZ | grep httpd
# 執行結果:

system_u:system_r:httpd_t:s0      828 ?        00:00:03 php-fpm
system_u:system_r:httpd_t:s0      829 ?        00:00:03 httpd

從上面可以看出 apache 相關的 process:httpd、php-fpm,它們所屬的 context 標籤都是 httpd_t

查詢 Port 的 Security Context

使用 semanage 這個工具可以查詢有關 port 方面的資訊

semanage port -l | grep http
# 執行結果:

http_cache_port_t              tcp      8080, 8118, 8123, 10001-10010
http_cache_port_t              udp      3130
http_port_t                    tcp      80, 81, 443, 488, 8008, 8009, 8443,9000
pegasus_http_port_t            tcp      5988
pegasus_https_port_t           tcp      5989

上面可以看到 apache 可以使用的 port 為 80、81、443…這些大家常用的 port,這也意味著,如果你的 Apache 想要使用上述以外的 port,在 SELinux 預設規則下是禁止的,因此網頁將無法透過自訂的 port 連上!

SELinux 常用指令

1. 檢查 SELinux 的狀態

getenforce

這個指令可以顯示 SELinux 目前的使用情形,一共有三種狀態

  • enforcing:強制使用,一般正常的啟動都是這個狀態,SELinux 會如實的運作。
  • permissive:寬容模式,在這個模式下,SELinux 會如 enforcing 模式一樣將各種訊息寫入 log 以供查詢, 但不會真的限制程式的存取,因此在安全防護上等於沒有,可以把它當成 debug 模式。
  • disabled:停用。

2. 切換 SELinux 模式

A. 完整切換

SELinux 模式的切換可以在 /etc/selinux/config 檔案裡設定,內容如下

# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.
SELINUX=enforcing
# SELINUXTYPE= can take one of three values:
#     targeted - Targeted processes are protected,
#     minimum - Modification of targeted policy. Only selected processesare protected.
#     mls - Multi Level Security protection.
SELINUXTYPE=targeted

SELinux= 這個選項後面即可調整想要使用的模式

變更模式後,需重開機才會生效

B. 快速切換

雖然完整切換方式可以調的東西比較多,但很多時候我們只是想確認問題是不是 SELinux 所引起的,如果用改 config 的方式來調整必須重開機才可以生效,非常麻煩。這時候我們就可以用另一個方法來切換。

sudo setenforce 0
sudo setenforce 1

setenforce 指令後面接 0 ,會立即將 SELinux 切到 Permissive 模式,指令後接 1 則切換回 enforcing 模式,而且不用重開機即可生效,很適合即時檢查用!

一旦發現有東西無法跑就先用 setenforce 0 來確定是不是 SELinux 在搞鬼!

3. 查詢應用程式的 SELinux 規則

大多數的應用程式都有它專屬的 SELinux 二元值規則,下面兩個指令都可以用來查看系統中所有 SELinux 規則的啟動與否。

getsebool -a
sestatus -b

執行後會列出一大串的規則,由於這邊要看的是 apache 相關的設定,因此我們只查看與 httpd 有關的規則。

sestatus -b | grep httpd
# 執行結果:

httpd_anon_write                            off
httpd_builtin_scripting                     on
httpd_can_check_spam                        off
httpd_can_connect_ftp                       off
httpd_can_connect_ldap                      off
httpd_can_connect_mythtv                    off
httpd_can_connect_zabbix                    off
httpd_can_network_connect                   off
httpd_can_network_connect_cobbler           off
httpd_can_network_connect_db                off
httpd_can_network_memcache                  off
httpd_can_network_relay                     off
...

4. 查詢資料夾預設的 context 標籤

安裝 semanage

sudo yum install policycoreutils-python-utils
sudo semanage fcontext -l
# 執行結果:

/var/www(/.*)?                                     all files         system_u:object_r:httpd_sys_content_t:s0 
/var/www(/.*)?/logs(/.*)?                          all files         system_u:object_r:httpd_log_t:s0 
/var/www/[^/]*/cgi-bin(/.*)?                       all files         system_u:object_r:httpd_sys_script_exec_t:s0 
/var/www/git(/.*)?                                 all files         system_u:object_r:git_content_t:s0 
/var/www/html(/.*)?/sites/default/files(/.*)?      all files         system_u:object_r:httpd_sys_rw_content_t:s0 
/var/www/html(/.*)?/sites/default/settings\.php    regular file      system_u:object_r:httpd_sys_rw_content_t:s0 
/var/www/html(/.*)?/uploads(/.*)?                  all files         system_u:object_r:httpd_sys_rw_content_t:s0 
/var/www/html(/.*)?/wp-content(/.*)?               all files         system_u:object_r:httpd_sys_rw_content_t:s0 
...

semanage fcontext -l 這個指令會列出系統裡全部的資料夾與所屬檔案的標籤,這邊節錄有關 /var/www 的內容。

5. 為檔案與資料夾自訂 context 標籤

sudo semanage fcontext -a -t home_t "/tmp/test(/.*)?"
  • -a:新增
  • -t:要新增的 type

-a-t 的參數可以為資料夾新增標籤,改完後再使用 semanage fcontext -l 查詢就可以看到剛才新增的項目,但新增的標籤不會立刻生效,要使用下面的 restorecon 指令才會生效。

6. 刪除所有自訂的 context 標籤

semanage fcontext -D

使用 -D 參數會將前一步驟裡所有自訂的標籤全部刪掉,回復成系統原本的預設狀態。刪除後一樣也是要使用 restorecon 才會正式生效。

7. 重新載入資料夾的預設 context 標籤

restorecon 這個指令會依照 semanage fcontext -l 所列出的 type ,去重設所有目標資料夾與檔案的標籤,有關這個指令的用法會在後面的實例中提到。

sudo restorecon -Rv /var/www/html
  • -R:將路徑裡所有的檔案、資料夾都一起修改
# 執行結果:
    
Relabeled /var/www/html from unconfined_u:object_r:httpd_sys_rw_content_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0

8. 修改檔案或資料夾的 context 標籤(常用)

chcon -R -t $context_TYPE /PATH
  • -R:將路徑底下所有的檔案、資料夾都一起修改
  • -t:想要用的 context type

chcon 這個指令可以立即的修改某個檔案或資料夾的 context 標籤,效果等同於前面第 5 步加上第 7步,好處是快速,但可能日後要做總查詢時會比較麻煩,不過 chcon 基本上算是最常用的修改方式。

問題排除教學:php 網頁無法上傳檔案

系統與軟體 CentOS 8 with Apache 2.4.37、PHP 7.2.11、MariaDB 15.1

檔案與目錄結構

# 檔案所在目錄
/var/www/html
    
# 目錄內容
drwxr-xr-x. 2 apache apache    6 Mar 26 22:34 upload       # 上傳檔案用的資料夾
-rw-r--r--. 1 apache apache  287 Mar 25 18:39 index.html   # 上傳用的 HTML 頁
-rw-r--r--. 1 apache apache 1064 Mar 26 20:14 upload.php   # 執行上傳與檢視的PHP 頁面

這個例子是以前練習 php 時碰到的問題

系統上有我寫的 php 網頁,這個網頁可以將檔案上傳到伺服器裡。正常的情況下,瀏覽器連上伺服器後,網頁會讓使用者上傳檔案,選擇檔案並上傳後,upload.php 會執行上傳的動作,上傳後檔案會存放在 /var/www/upload 資料夾中,且上傳成功的話,頁面會顯示出已上傳的檔案連結供下載。

檔案上傳頁面

上傳成功


雖然理想情況是這樣,但我發現每次上傳後,PHP 網頁顯示上傳成功,但點擊連結後,顯示檔案不存在,表示檔案沒有真的上傳成功…

顯示上傳成功但無法開啟圖片

確認是否為 SELinux 的問題

如果我們伺服器的防火牆開通了、資料夾權限也正確,但怎樣上傳就是失敗,這時候就先使用 getenforce 指令查看 SELinux 的狀態

getenforce

如果執行結果為 Enforcing,那就執行 setenforce 0,將 SELinux 切換到 permissive 模式

sudo setenforce 0

確認切換到 Permissive 後,再試一次上傳看是否能夠成功開啟檔案,成功的話,那就可以確定是 SELinux 的問題了。

查詢檔案與程式的 SELinux context 標籤類型

ls  -alZ /var/www/html
# 執行結果:

total 8
drwxr-xr-x. 3 root   root   system_u:object_r:httpd_sys_content_t:s0          56 Mar 28 00:03 .
drwxr-xr-x. 4 root   root   system_u:object_r:httpd_sys_content_t:s0          33 Mar 28 00:04 ..
-rw-r--r--. 1 apache apache unconfined_u:object_r:httpd_sys_content_t:s0  287 Mar 28 16:50 index.html
drwxr-xr-x. 2 apache apache unconfined_u:object_r:httpd_sys_content_t:s0    6 Mar 28 17:11 upload
-rw-r--r--. 1 apache apache unconfined_u:object_r:httpd_sys_content_t:s0 1064 Mar 28 17:10 upload.php

查詢後顯示 /var/www/html 與裡面三個檔案的 context 標籤都是 httpd_sys_content_t

查詢 process 的 SELinux context type

ps -eZ | grep httpd
# 執行結果:

system_u:system_r:httpd_t:s0      2308 ?        00:00:09 php-fpm
system_u:system_r:httpd_t:s0      8469 ?        00:00:06 httpd

從上面指令得知 httpd 與 php-fpm 這兩個程序的 context type 為 httpd_t,接著我們來查詢 httpd_t 這個標籤對於讀寫資料的權限

查詢 httpd_t 對於檔案讀寫權限的 context type

首先,安裝 sesearch,這是一個 SELinux 規則的查詢程式

sudo yum install setools-console
sudo sesearch -A -s httpd_t -c file -p read -p write

上面指令的意思為:尋找所有允許 httpd_t 讀寫檔案或目錄的規則

  • -A:搜尋所有 allow 的規則
  • -s:指定搜尋的來源類型,即本例的 httpd_t
  • -c:指定規則所作用的對象,本例為 file,表示想搜尋對於檔案存取權限的規則
  • -p:選擇作用於對象的行為,本例為 read 與write
# 執行結果

allow httpd_t dspam_rw_content_t:file { append create getattr ioctl link lock open read rename setattr unlink write }; [ httpd_builtin_scripting ]:True
allow httpd_t fusefs_t:file { append create getattr ioctl link lock open read rename setattr unlink write }; [ httpd_use_fusefs ]:True
allow httpd_t git_rw_content_t:file { append create getattr ioctl link lock open read rename setattr unlink write }; [ httpd_builtin_scripting ]:True
allow httpd_t httpd_cache_t:file { append create getattr ioctl link lock map open read rename setattr unlink write };
allow httpd_t httpd_lock_t:file { append create getattr ioctl link lock open read rename setattr unlink write };
allow httpd_t httpd_squirrelmail_t:file { append create getattr ioctl link lock map open read rename setattr unlink write };
allow httpd_t httpd_sys_rw_content_t:file { append create getattr ioctl link lock open read rename setattr unlink write }; [ ( httpd_builtin_scripting && httpd_unified && httpd_enable_cgi ) ]:True

搜尋後,我們會發現 upload 資料夾所屬的 httpd_sys_content_t 並沒有出現,這就表示標籤為 httpd_t 的 httpd 這個 process 是無法對 upload 資料夾做寫入動作的! 因此會發生我們網頁顯示正常,但上傳檔案會失敗的問題。

接著注意到這行:

allow httpd_t httpd_sys_rw_content_t

allow 後面接主體程序以及檔案的 SELinux 標籤,上面這行的意思是指:httpd_t 可以讀寫標籤為 httpd_sys_rw_content_t 的檔案 or 目錄,所以如果希望 upload 可以被 apache 讀寫,好讓我們上傳檔案,可以將該目錄的標籤設為 httpd_sys_rw_content_t

上面 sesearch 指令的結果只是節錄,實際上的條目更多,以 httpd_sys_rw_content_t 為例是因為光從字面上看也大概猜得到它是與 Apache 的讀寫權限有關,實際上只要資料夾改成上面搜尋到的任何一個 label 都是可以讓 apache 讀寫的。

修改檔案或目錄的 SELinux context 標籤

既然知道我們 upload 資料夾預設是不給 httpd 寫入的,接下來我們就要將它的標籤換成可以寫入的標籤,修改檔案或目錄的 SELinux context 標籤有三種方法:

1. 使用 chcon 指令直接修改

chcon -R -t httpd_sys_rw_content_t /var/www/html/upload
  • -R:將路徑底下所有的檔案、資料夾都一起修改
  • -t:想要用的 context type,,例如 httpd_sys_rw_content_t

chcon 這個指令,可以將 /var/www/html/upload 及它裡面檔案、目錄的 context 標籤立即改掉,算是最簡單快速的修改方法。接著再次檢查,確認是否已修改完成

ls -lZ /var/www/html/
# 執行結果:

-rw-r--r--. 1 apache apache unconfined_u:object_r:httpd_sys_content_t:s0     287 Mar 28 16:50 index.html
drwxr-xr-x. 2 apache apache unconfined_u:object_r:httpd_sys_rw_content_t:s0    6 Mar 28 17:11 upload
-rw-r--r--. 1 apache apache unconfined_u:object_r:httpd_sys_content_t:s0    1064 Mar 28 17:10 upload.php
    

upload 資料夾已更改成功,接著再重新測一次網頁的上傳 ,應該就可以上傳成功並開啟檔案了!

2. 為檔案或目錄新增自訂標籤

前面有提過 restorecon 這個指令的用途是將檔案、目錄的 SELinux context 標籤還原成系統預設的標籤。在上面的方法中,我們用 chcon 將 upload 的標籤改成了 httpd_sys_rw_content_t,但如果我們對這個目錄用了 restorecon,你會發現 upload 的標籤從 httpd_sys_rw_content_t 又還原成原本的 httpd_sys_content_t

sudo restorecon -Rv /var/www/html/upload
# 執行結果:

Relabeled /var/www/html/upload from unconfined_u:object_r:httpd_sys_rw_content_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0


從這裡可以看得出來,用 chcon 來改其實還蠻有彈性的,因為隨時可以還原,但如果我們不希望檔案的 context 標籤可以被輕易的還原,這時候我們可以用 semanage 來為檔案或資料夾新增一個自訂的 context 標籤

semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/html/upload(/.*)?"

上面指令的意思是為將 httpd_sys_rw_content_t 設定為 /var/www/html/upload 與它裡面東西的預設 context 標籤

這行指令執行完後,可以用上面試過的 semsnage fcontext -l 來查詢規則是否已建立

sudo semanage fcontext -l | grep '/var/www/html' | grep 'upload'
# 執行結果:

/var/www/html(/.*)?/uploads(/.*)?                  all files          system_u:object_r:httpd_sys_rw_content_t:s0 
/var/www/html/upload(/.*)?                         all files          system_u:object_r:httpd_sys_rw_content_t:s0 

可以看到預設的規則裡多了一條專屬於 /var/www/html/upload 目錄的規則了

semanage fcontext -a -t 的指令只是為資料夾新增了規則,但目前資料夾的狀態並沒有因為規則的建立而讓 apache 可讀寫,這時要用上面提到的 restorecon 指令將資料夾重整成它應有的標籤

sudo restorecon -Rv /var/www/html/upload
# 執行結果:

Relabeled /var/www/html/upload from unconfined_u:object_r:httpd_sys_content_t:s0 to unconfined_u:object_r:httpd_sys_rw_content_t:s0

接著檢查 upload 資料夾目前的狀態

ls -lZ /var/www/html/
# 執行結果:

-rw-r--r--. 1 apache apache unconfined_u:object_r:httpd_sys_content_t:s0     287 Mar 28 16:50 index.html
drwxr-xr-x. 2 apache apache unconfined_u:object_r:httpd_sys_rw_content_t:s0    6 Mar 28 17:11 upload
-rw-r--r--. 1 apache apache unconfined_u:object_r:httpd_sys_content_t:s0    1064 Mar 28 17:10 upload.php

我們會發現,同樣是執行 restorecon -Rv 的指令,但這次 upload 的標籤變成了可讀寫的 httpd_sys_rw_content_t,而不是剛才的 httpd_sys_content_t,這就是由於我們先使用 semanage 為 upload 新增了自訂規則的綠故!

3. 套用其它資料夾的設定

前面我們使用 semanage fcontext -l 查詢時,有看到一個預設的規則

sudo semanage fcontext -l | grep '/var/www/html' | grep 'upload'
# 執行結果:
    
/var/www/html(/.*)?/uploads(/.*)?                  all files          system_u:object_r:httpd_sys_rw_content_t:s0 

這邊的意思是如果在 /var/www/html/ 裡有一個叫 uploads 的資料夾, 那麼系統會自動預設它的 context 標籤會是 httpd_sys_rw_content_t,也就是允許 apache 讀寫的 type。

為了驗證這點,我們先在 /var/www/html 裡建一個 uploads 的資料夾

sudo mkdir /var/www/html/uploads
ls -lZ /var/www/html
# 執行結果:

-rw-r--r--. 1 apache apache unconfined_u:object_r:httpd_sys_content_t:s0     287 Mar 28 16:50 index.html
drwxr-xr-x. 2 apache apache unconfined_u:object_r:httpd_sys_content_t:s0    6 Mar 28 17:11 upload
-rw-r--r--. 1 apache apache unconfined_u:object_r:httpd_sys_content_t:s0    1064 Mar 28 17:10 upload.php
drwxr-xr-x. 2 root   root   unconfined_u:object_r:httpd_sys_rw_content_t:s0    6 Mar 29 02:39 uploads

可以看到剛才建的 uploads 資料夾果然是可讀寫的 httpd_sys_rw_content_t

由於我上傳的資料夾是命名為 upload,而非 uploads,因此預設為不可讀寫,這時我們可以用參照現有檔案的方式來新增資料夾的預設格式

sudo semanage fcontext -a -e /var/www/html/uploads /var/www/html/upload

意思是:新增一條規則,規則為:將 /var/www/html/uploads 的 context type 套用到 /var/www/html/upload 上面,因此 /var/www/html/upload 的規則就會與 uploads 一樣,都是可被 apache 讀寫的 type。

接著一樣再用 restorecon -R -v 重新整理一次 /var/www/html

sudo restorecon -R -v /var/www/html
# 執行結果:
    
Relabeled /var/www/html/upload from unconfined_u:object_r:httpd_sys_content_t:s0 to unconfined_u:object_r:httpd_sys_rw_content_t:s0
ls -lZ /var/www/html
# 執行結果:

-rw-r--r--. 1 apache apache unconfined_u:object_r:httpd_sys_content_t:s0     287 Mar 28 16:50 index.html
drwxr-xr-x. 2 apache apache unconfined_u:object_r:httpd_sys_rw_content_t:s0    6 Mar 28 17:11 upload
-rw-r--r--. 1 apache apache unconfined_u:object_r:httpd_sys_content_t:s0    1064 Mar 28 17:10 upload.php
drwxr-xr-x. 2 root   root   unconfined_u:object_r:httpd_sys_rw_content_t:s0    6 Mar 29 02:39 uploads

可以看到 upload 與 uploads 一樣都是可讀寫的 httpd_sys_rw_content_t 了,最後再次驗證 php 網頁,就可以順利上傳成功啦!

問題排除教學 :PHP 無法連線 MariaDB 資料庫

這個問題在 SELinux 設定 for Apache 存取 DataBase 這篇文章裡也有教學,不過這篇全部講 SELinux 的文章裡再拿來騙一下字數(又沒錢…)

這次碰到的是 PHP 的網頁無法連接資料庫,已確定在 MariaDB 裡是有允許本機的連線,在使用 setenforce 關閉 SELinux 後,發現果然又是它在作怪,下面為解決的方法:

查詢 Apache 與連線相關的 SELinux 二元值規則

sestatus -b | grep 'httpd' | grep 'connect'
# 執行結果:

httpd_can_connect_ftp                       off
httpd_can_connect_ldap                      off
httpd_can_connect_mythtv                    off
httpd_can_connect_zabbix                    off
httpd_can_network_connect                   off
httpd_can_network_connect_cobbler           off
httpd_can_network_connect_db                off

從上面大概就可以看到許多端倪,有的是允許 apache 連線 ftp,有的是允許連 zabbix,而我們這邊的重點就在最後一行,httpd_can_network_connect_db,這個怎麼看都跟與 DB 的連線有關,但它竟然是 off,因此我們可以試著將它打開

sudo setsebool -P httpd_can_network_connect_db 1
sudo setsebool -P httpd_can_network_connect_db on

這兩個指令是一樣的,打開這個選項後,PHP 就可以順利的連線到 MariaDB 了!

問題排除教學 :Apache 無法使用自訂 Port 號

一般的情況下,web server 通常使用 80、81、443 之類的 port

81 也是 httpd 常用的 port

但如果我的 web server 想使用個比較特別的 port 號,例如 808 port,在更改 port 並重啟 httpd 後,會發現無法正常的啟動 apache:

sudo systemctl restart httpd
# 執行結果:

Job for httpd.service failed because the control process exited with errorcode.
See "systemctl status httpd.service" and "journalctl -xe" for details.


更改 port 號為 808 後重啟 httpd,會啟動失敗

sudo systemctl status httpd
# 執行結果:

● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
  Drop-In: /usr/lib/systemd/system/httpd.service.d
           └─php-fpm.conf
   Active: failed (Result: exit-code) since Wed 2020-04-01 23:23:39 CST; 24s ago
     Docs: man:httpd.service(8)
  Process: 1851 ExecStart=/usr/sbin/httpd $OPTIONS -DFOREGROUND (code=exited, status=1/FAILURE)
 Main PID: 1851 (code=exited, status=1/FAILURE)
   Status: "Reading configuration..."

Apr 01 23:23:38 lamp systemd[1]: Starting The Apache HTTP Server...
Apr 01 23:23:39 lamp httpd[1851]: AH00558: httpd: Could not reliably determine the server's fully qualified domain name>
Apr 01 23:23:39 lamp httpd[1851]: (13)Permission denied: AH00072: make_sock: could not bind to address [::]:808
Apr 01 23:23:39 lamp httpd[1851]: (13)Permission denied: AH00072: make_sock: could not bind to address 0.0.0.0:808
Apr 01 23:23:39 lamp httpd[1851]: no listening sockets available, shutting down
Apr 01 23:23:39 lamp httpd[1851]: AH00015: Unable to open logs
Apr 01 23:23:39 lamp systemd[1]: httpd.service: Main process exited, code=exited, status=1/FAILURE
Apr 01 23:23:39 lamp systemd[1]: httpd.service: Failed with result 'exit-code'.
Apr 01 23:23:39 lamp systemd[1]: Failed to start The Apache HTTP Server.

error log 會直接告訴你有權限上的問題

前面我們有提過,SELinux 除了管理程式對檔案與資料夾的存取以外,也會管理程式對於 Port 的使用。基本上我們常見或不常見的幾個 service,都是有固定使用的 port 號,例如 ssh 用 22 port,httpd 就是 80 與 443 port。

sudo semanage port -l | grep http
# 執行結果:

http_cache_port_t              tcp      8080, 8118, 8123, 10001-10010
http_cache_port_t              udp      3130
http_port_t                    tcp      80, 81, 443, 488, 8008, 8009, 8443,9000
pegasus_http_port_t            tcp      5988
pegasus_https_port_t           tcp      5989

使用 semanage port -l,可以列出所有應用程式在 SELinux 中被允許使用的 port。從上面的結果可以得知 apache 預設可以使用 80、81、443…等 port 號。而 808 這個 port 號是我自己爽用的,所以當然不可能會是 SELinux 允許的 httpd port 號。

這種情況下,我們必須在 http_port_t 這個 context 中額外加上 808,這樣才可以順利的使用 808 port 來瀏覽我的網站。

為 Port 相關的 context 新增額外 Port 號

下面的指令可以將 http_port_t 新增 808 port

sudo semanage port -a -t http_port_t -p tcp 808
sudo semanage port -l | grep http
# 執行結果:

http_cache_port_t              tcp      8080, 8118, 8123, 10001-10010
http_cache_port_t              udp      3130
http_port_t                    tcp      808, 80, 81, 443, 488, 8008, 8009, 8443, 9000
pegasus_http_port_t            tcp      5988
pegasus_https_port_t           tcp      5989

查詢後可以看到 httpd_port_t 新增了一個 808 port,最後啟動 httpd,就可以成功開啟了!

成功的使用 808 port 開啟網頁!

Cover By

wade Written by:

本站站長